home *** CD-ROM | disk | FTP | other *** search
/ Programming Windows (5th Edition) / Programming Windows, 5th ed. - Companion CD (097-0002183)(1999).iso / Chap17 / Justify1 / Justify1.c next >
Encoding:
C/C++ Source or Header  |  1998-10-09  |  12.6 KB  |  364 lines

  1. /*-----------------------------------------
  2.    JUSTIFY1.C -- Justified Type Program #1
  3.                  (c) Charles Petzold, 1998
  4.   -----------------------------------------*/
  5.  
  6. #include <windows.h>
  7. #include "resource.h"
  8.  
  9. LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
  10.  
  11. TCHAR szAppName[] = TEXT ("Justify1") ;
  12.  
  13. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
  14.                     PSTR szCmdLine, int iCmdShow)
  15. {
  16.      HWND     hwnd ;
  17.      MSG      msg ;
  18.      WNDCLASS wndclass ;
  19.      
  20.      wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
  21.      wndclass.lpfnWndProc   = WndProc ;
  22.      wndclass.cbClsExtra    = 0 ;
  23.      wndclass.cbWndExtra    = 0 ;
  24.      wndclass.hInstance     = hInstance ;
  25.      wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
  26.      wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  27.      wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
  28.      wndclass.lpszMenuName  = szAppName ;
  29.      wndclass.lpszClassName = szAppName ;
  30.      
  31.      if (!RegisterClass (&wndclass))
  32.      {
  33.           MessageBox (NULL, TEXT ("This program requires Windows NT!"),
  34.                szAppName, MB_ICONERROR) ;
  35.           return 0 ;
  36.      }
  37.      
  38.      hwnd = CreateWindow (szAppName, TEXT ("Justified Type #1"),
  39.                           WS_OVERLAPPEDWINDOW,
  40.                           CW_USEDEFAULT, CW_USEDEFAULT,
  41.                           CW_USEDEFAULT, CW_USEDEFAULT,
  42.                           NULL, NULL, hInstance, NULL) ;
  43.      
  44.      ShowWindow (hwnd, iCmdShow) ;
  45.      UpdateWindow (hwnd) ;
  46.      
  47.      while (GetMessage (&msg, NULL, 0, 0))
  48.      {
  49.           TranslateMessage (&msg) ;
  50.           DispatchMessage (&msg) ;
  51.      }
  52.      return msg.wParam ;
  53. }
  54.  
  55. void DrawRuler (HDC hdc, RECT * prc)
  56. {
  57.      static int iRuleSize [16] = { 360, 72, 144, 72, 216, 72, 144, 72,
  58.                                    288, 72, 144, 72, 216, 72, 144, 72 } ;
  59.      int        i, j ;
  60.      POINT      ptClient ;
  61.      
  62.      SaveDC (hdc) ;
  63.      
  64.           // Set Logical Twips mapping mode
  65.      
  66.      SetMapMode (hdc, MM_ANISOTROPIC) ;
  67.      SetWindowExtEx (hdc, 1440, 1440, NULL) ;
  68.      SetViewportExtEx (hdc, GetDeviceCaps (hdc, LOGPIXELSX),
  69.                             GetDeviceCaps (hdc, LOGPIXELSY), NULL) ;
  70.      
  71.           // Move the origin to a half inch from upper left
  72.      
  73.      SetWindowOrgEx (hdc, -720, -720, NULL) ;
  74.      
  75.           // Find the right margin (quarter inch from right)
  76.      
  77.      ptClient.x = prc->right ;
  78.      ptClient.y = prc->bottom ;
  79.      DPtoLP (hdc, &ptClient, 1) ;
  80.      ptClient.x -= 360 ;
  81.      
  82.           // Draw the rulers
  83.      
  84.      MoveToEx (hdc, 0,          -360, NULL) ;
  85.      LineTo   (hdc, ptClient.x, -360) ;
  86.      MoveToEx (hdc, -360,          0, NULL) ;
  87.      LineTo   (hdc, -360, ptClient.y) ;
  88.      
  89.      for (i = 0, j = 0 ; i <= ptClient.x ; i += 1440 / 16, j++)
  90.      {
  91.           MoveToEx (hdc, i, -360, NULL) ;
  92.           LineTo   (hdc, i, -360 - iRuleSize [j % 16]) ;
  93.      }
  94.      
  95.      for (i = 0, j = 0 ; i <= ptClient.y ; i += 1440 / 16, j++)
  96.      {
  97.           MoveToEx (hdc, -360, i, NULL) ;
  98.           LineTo   (hdc, -360 - iRuleSize [j % 16], i) ;
  99.      }
  100.      
  101.      RestoreDC (hdc, -1) ;
  102. }
  103.  
  104. void Justify (HDC hdc, PTSTR pText, RECT * prc, int iAlign)
  105. {
  106.      int   xStart, yStart, cSpaceChars ;
  107.      PTSTR pBegin, pEnd ;
  108.      SIZE  size ;
  109.      
  110.      yStart = prc->top ;
  111.      do                            // for each text line
  112.      {
  113.           cSpaceChars = 0 ;        // initialize number of spaces in line
  114.  
  115.           while (*pText == ' ')    // skip over leading spaces
  116.                pText++ ;
  117.  
  118.           pBegin = pText ;         // set pointer to char at beginning of line
  119.           
  120.           do                       // until the line is known
  121.           {
  122.                pEnd = pText ;      // set pointer to char at end of line
  123.  
  124.                     // skip to next space 
  125.                
  126.                while (*pText != '\0' && *pText++ != ' ') ;
  127.  
  128.                if (*pText == '\0')
  129.                     break ;
  130.  
  131.                     // after each space encountered, calculate extents
  132.  
  133.                cSpaceChars++ ;
  134.                GetTextExtentPoint32(hdc, pBegin, pText - pBegin - 1, &size) ;
  135.           }
  136.           while (size.cx < (prc->right - prc->left)) ;
  137.           
  138.           cSpaceChars-- ;               // discount last space at end of line
  139.           
  140.           while (*(pEnd - 1) == ' ')    // eliminate trailing spaces
  141.           {
  142.                pEnd-- ;
  143.                cSpaceChars-- ;
  144.           }
  145.  
  146.                // if end of text and no space characters, set pEnd to end
  147.           
  148.           if (*pText == '\0' || cSpaceChars <= 0)
  149.                pEnd = pText ;
  150.           
  151.           GetTextExtentPoint32 (hdc, pBegin, pEnd - pBegin, &size) ;
  152.           
  153.           switch (iAlign)               // use alignment for xStart
  154.           {
  155.           case IDM_ALIGN_LEFT:
  156.                xStart = prc->left ;
  157.                break ;
  158.                
  159.           case IDM_ALIGN_RIGHT:
  160.                xStart = prc->right - size.cx ;
  161.                break ;
  162.                
  163.           case IDM_ALIGN_CENTER:
  164.                xStart = (prc->right + prc->left - size.cx) / 2 ;
  165.                break ;
  166.                
  167.           case IDM_ALIGN_JUSTIFIED:
  168.                if (*pText != '\0' && cSpaceChars > 0)
  169.                     SetTextJustification (hdc,
  170.                                           prc->right - prc->left - size.cx,
  171.                                           cSpaceChars) ;
  172.                xStart = prc->left ;
  173.                break ;
  174.           }
  175.                // display the text
  176.           
  177.           TextOut (hdc, xStart, yStart, pBegin, pEnd - pBegin) ;
  178.  
  179.                // prepare for next line
  180.  
  181.           SetTextJustification (hdc, 0, 0) ;
  182.           yStart += size.cy ;
  183.           pText = pEnd ;
  184.      }
  185.      while (*pText && yStart < prc->bottom - size.cy) ;
  186. }
  187.  
  188. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  189. {
  190.      static CHOOSEFONT cf ;
  191.      static DOCINFO    di = { sizeof (DOCINFO), TEXT ("Justify1: Printing") } ;
  192.      static int        iAlign = IDM_ALIGN_LEFT ;
  193.      static LOGFONT    lf ;
  194.      static PRINTDLG   pd ;
  195.      static TCHAR      szText[] = { 
  196.                               TEXT ("You don't know about me, without you ")
  197.                               TEXT ("have read a book by the name of \"The ")
  198.                               TEXT ("Adventures of Tom Sawyer,\" but that ")
  199.                               TEXT ("ain't no matter. That book was made by ")
  200.                               TEXT ("Mr. Mark Twain, and he told the truth, ")
  201.                               TEXT ("mainly. There was things which he ")
  202.                               TEXT ("stretched, but mainly he told the truth. ")
  203.                               TEXT ("That is nothing. I never seen anybody ")
  204.                               TEXT ("but lied, one time or another, without ")
  205.                               TEXT ("it was Aunt Polly, or the widow, or ")
  206.                               TEXT ("maybe Mary. Aunt Polly -- Tom's Aunt ")
  207.                               TEXT ("Polly, she is -- and Mary, and the Widow ")
  208.                               TEXT ("Douglas, is all told about in that book ")
  209.                               TEXT ("-- which is mostly a true book; with ")
  210.                               TEXT ("some stretchers, as I said before.") } ;
  211.      BOOL              fSuccess ;
  212.      HDC               hdc, hdcPrn ;
  213.      HMENU             hMenu ;
  214.      int               iSavePointSize ;
  215.      PAINTSTRUCT       ps ;
  216.      RECT              rect ;
  217.      
  218.      switch (message)
  219.      {
  220.      case WM_CREATE:
  221.                // Initialize the CHOOSEFONT structure
  222.  
  223.           GetObject (GetStockObject (SYSTEM_FONT), sizeof (lf), &lf) ;
  224.  
  225.           cf.lStructSize    = sizeof (CHOOSEFONT) ;
  226.           cf.hwndOwner      = hwnd ;
  227.           cf.hDC            = NULL ;
  228.           cf.lpLogFont      = &lf ;
  229.           cf.iPointSize     = 0 ;
  230.           cf.Flags          = CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS | 
  231.                               CF_EFFECTS ;
  232.           cf.rgbColors      = 0 ;
  233.           cf.lCustData      = 0 ;
  234.           cf.lpfnHook       = NULL ;
  235.           cf.lpTemplateName = NULL ;
  236.           cf.hInstance      = NULL ;
  237.           cf.lpszStyle      = NULL ;
  238.           cf.nFontType      = 0 ;      
  239.           cf.nSizeMin       = 0 ;
  240.           cf.nSizeMax       = 0 ;
  241.   
  242.           return 0 ;
  243.  
  244.      case WM_COMMAND:
  245.           hMenu = GetMenu (hwnd) ;
  246.           
  247.           switch (LOWORD (wParam))
  248.           {
  249.           case IDM_FILE_PRINT:
  250.                                    // Get printer DC
  251.  
  252.                pd.lStructSize = sizeof (PRINTDLG) ;
  253.                pd.hwndOwner   = hwnd ;
  254.               pd.Flags       = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION ;
  255.  
  256.               if (!PrintDlg (&pd))
  257.                     return 0 ;
  258.  
  259.                if (NULL == (hdcPrn = pd.hDC))
  260.                {
  261.                     MessageBox (hwnd, TEXT ("Cannot obtain Printer DC"),
  262.                                 szAppName, MB_ICONEXCLAMATION | MB_OK) ;
  263.                     return 0 ;
  264.                }
  265.                     // Set margins of 1 inch
  266.  
  267.                rect.left   = GetDeviceCaps (hdcPrn, LOGPIXELSX) -
  268.                              GetDeviceCaps (hdcPrn, PHYSICALOFFSETX) ;
  269.  
  270.                rect.top    = GetDeviceCaps (hdcPrn, LOGPIXELSY) -
  271.                              GetDeviceCaps (hdcPrn, PHYSICALOFFSETY) ;
  272.  
  273.                rect.right  = GetDeviceCaps (hdcPrn, PHYSICALWIDTH) -
  274.                              GetDeviceCaps (hdcPrn, LOGPIXELSX) -
  275.                              GetDeviceCaps (hdcPrn, PHYSICALOFFSETX) ;
  276.  
  277.                rect.bottom = GetDeviceCaps (hdcPrn, PHYSICALHEIGHT) - 
  278.                              GetDeviceCaps (hdcPrn, LOGPIXELSY) -
  279.                              GetDeviceCaps (hdcPrn, PHYSICALOFFSETY) ;
  280.  
  281.                     // Display text on printer
  282.  
  283.                SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
  284.                ShowCursor (TRUE) ;
  285.  
  286.                fSuccess = FALSE ;
  287.  
  288.                if ((StartDoc (hdcPrn, &di) > 0) && (StartPage (hdcPrn) > 0))
  289.                {
  290.                          // Select font using adjusted lfHeight
  291.  
  292.                     iSavePointSize = lf.lfHeight ;
  293.                     lf.lfHeight = -(GetDeviceCaps (hdcPrn, LOGPIXELSY) *
  294.                                          cf.iPointSize) / 720 ;
  295.  
  296.                     SelectObject (hdcPrn, CreateFontIndirect (&lf)) ;
  297.                     lf.lfHeight = iSavePointSize ;
  298.  
  299.                          // Set text color 
  300.  
  301.                     SetTextColor (hdcPrn, cf.rgbColors) ;
  302.                
  303.                          // Display text
  304.  
  305.                     Justify (hdcPrn, szText, &rect, iAlign) ;
  306.  
  307.                     if (EndPage (hdcPrn) > 0)
  308.                     {
  309.                          fSuccess = TRUE ;
  310.                          EndDoc (hdcPrn) ;
  311.                     }
  312.                }
  313.                ShowCursor (FALSE) ;
  314.                SetCursor (LoadCursor (NULL, IDC_ARROW)) ;
  315.  
  316.                DeleteDC (hdcPrn) ;
  317.  
  318.                if (!fSuccess)
  319.                     MessageBox (hwnd, TEXT ("Could not print text"),
  320.                                 szAppName, MB_ICONEXCLAMATION | MB_OK) ;
  321.                return 0 ;
  322.  
  323.           case IDM_FONT:
  324.                if (ChooseFont (&cf))
  325.                     InvalidateRect (hwnd, NULL, TRUE) ;
  326.                return 0 ;
  327.                
  328.           case IDM_ALIGN_LEFT:
  329.           case IDM_ALIGN_RIGHT:
  330.           case IDM_ALIGN_CENTER:
  331.           case IDM_ALIGN_JUSTIFIED:
  332.                CheckMenuItem (hMenu, iAlign, MF_UNCHECKED) ;
  333.                iAlign = LOWORD (wParam) ;
  334.                CheckMenuItem (hMenu, iAlign, MF_CHECKED) ;
  335.                InvalidateRect (hwnd, NULL, TRUE) ;
  336.                return 0 ;
  337.           }
  338.           return 0 ;
  339.  
  340.      case WM_PAINT:
  341.           hdc = BeginPaint (hwnd, &ps) ;
  342.           
  343.           GetClientRect (hwnd, &rect) ;
  344.           DrawRuler (hdc, &rect) ;
  345.           
  346.           rect.left  += GetDeviceCaps (hdc, LOGPIXELSX) / 2 ;
  347.           rect.top   += GetDeviceCaps (hdc, LOGPIXELSY) / 2 ;
  348.           rect.right -= GetDeviceCaps (hdc, LOGPIXELSX) / 4 ;
  349.  
  350.           SelectObject (hdc, CreateFontIndirect (&lf)) ;
  351.           SetTextColor (hdc, cf.rgbColors) ;
  352.           
  353.           Justify (hdc, szText, &rect, iAlign) ;
  354.           
  355.           DeleteObject (SelectObject (hdc, GetStockObject (SYSTEM_FONT)));
  356.           EndPaint (hwnd, &ps) ;
  357.           return 0 ;
  358.           
  359.      case WM_DESTROY:
  360.           PostQuitMessage (0) ;
  361.           return 0 ;
  362.      }
  363.      return DefWindowProc (hwnd, message, wParam, lParam) ;
  364. }